package com.ljkj.cordial.chat.util;

import android.annotation.SuppressLint;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Message;
import android.support.v4.content.ContextCompat;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.google.protobuf.ByteString;
import com.ljkj.cordial.chat.base.ChatApp;
import com.ljkj.cordial.chat.dao.AlbumTableBean;
import com.ljkj.cordial.chat.notify.PromptTone;
import com.ljkj.cordial.lengthtcpheartbeat.ByteStringUtil;
import com.nic.view.util.JLog;
import com.nic.view.util.JToast;
import com.nic.view.util.Utility;
import com.nic.view.widget.AudioRecorder;
import com.nic.view.widget.VoiceDialog;
import com.yanzhenjie.album.AlbumFile;
import com.yanzhenjie.album.util.AlbumUtils;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 录音工具
 */
public class SpeechVoiceUtil {
    private final int TIME_LENGTH = 60 * 1000;
    /**
     * true正在录音,false没有录音
     */
    private boolean isRecord = false;


    private int SPACE = 100;// 声音分贝间隔取样时间
    private long duration;//时长

    //    private VoiceDialog voiceToast;
    private AudioRecorder mAudioRecorder;
    private String filePath;
    private Context context;
    private TextView tvSpeech;
    private VoiceDialog voiceToast;
    private int maxSpeechTime;
    private ExecutorService exec;

    private Runnable mUpdateMicStatusTimer = this::updateMicStatus;

    public int getMaxSpeechTime() {
        return maxSpeechTime == 0 ? TIME_LENGTH : maxSpeechTime;
    }

    public void setMaxSpeechTime(int maxSpeechTime) {
        this.maxSpeechTime = maxSpeechTime;
    }

    private static class Build {
        public static SpeechVoiceUtil INSTANCE = new SpeechVoiceUtil();
    }

    public static SpeechVoiceUtil getInstance() {
        return Build.INSTANCE;
    }

    public SpeechVoiceUtil() {


    }

    @SuppressLint("ClickableViewAccessibility")
    public SpeechVoiceUtil init(Context context, TextView tvSpeech, OnSpeechResultCallback callback) {
        this.context = context;
        voiceToast = new VoiceDialog(context);
        voiceToast.getAnticlockwise().setOnStartCountdownListener(() -> PromptTone.vibrate(context, 100));
        tvSpeech.setOnTouchListener(speechTouch);
        this.tvSpeech = tvSpeech;
        this.callback = callback;
        exec = Executors.newSingleThreadExecutor();
        if (mAudioRecorder == null) {
            mAudioRecorder = new AudioRecorder();
            mAudioRecorder.setMaxDuration(getMaxSpeechTime());
        }

        return this;
    }

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 0) {//开始
                tvSpeech.setText("松开 结束");
                tvSpeech.setBackground(ContextCompat.getDrawable(context, com.nic.view.R.drawable.bg_gray_rec));
                startRecord();
            } else if (msg.what == 1) {//结束
//                if ((System.currentTimeMillis() - starMillis) / 1000 == getMaxSpeechTime()) {
//                    JToast.show(context, "已达到录制上限！", Toast.LENGTH_SHORT);
//                }
                tvSpeech.setText("按住 说话");
                tvSpeech.setBackground(ContextCompat.getDrawable(context, com.nic.view.R.drawable.bg_white_rec));
                stopRecord();
                removeCallbacks(null);
            }
        }
    };

    private float mActionDownY;
    private boolean isCancel;
    private final static int CANCEL_DISTANCE = 200;
    /**
     * 录音按钮的触摸事件
     */
    private View.OnTouchListener speechTouch = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    PromptTone.vibrate(context, 100);
                    isCancel = false;
                    mActionDownY = event.getY();
                    voiceToast.getAnticlockwise().reStart(TIME_LENGTH / 1000);
                    handler.sendEmptyMessageDelayed(1, getMaxSpeechTime() + 500);
                    handler.sendEmptyMessage(0);
                    if (callback != null)
                        callback.onStart();
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    if (handler.hasMessages(1)) {
                        handler.removeMessages(1);
                    }
                    float mActionUpY = event.getY();
                    isCancel = abs(mActionUpY - mActionDownY) > CANCEL_DISTANCE;
                    handler.sendEmptyMessage(1);
                    break;
                case MotionEvent.ACTION_MOVE:
                    float mActionMoveY = event.getY();
                    if (abs(mActionMoveY - mActionDownY) > CANCEL_DISTANCE) {
                        voiceToast.setPrompt("松开手指，取消发送");
                        voiceToast.setLogo(com.nic.view.R.mipmap.dialog_popup_mic_cancel);
                        tvSpeech.setText("松开 取消");
                    } else if (abs(mActionMoveY - mActionDownY) <= 50) {
                        voiceToast.setPrompt("手指上滑，取消发送");
                        voiceToast.setLogo(com.nic.view.R.mipmap.dialog_popup_mic);
                        tvSpeech.setText("松开 结束");
                    }

                    break;
            }
            return true;
        }
    };

    public float abs(float a) {
        if (a < 0)
            return -a;
        return a;
    }

    /**
     * 开始录音
     */
    private void startRecord() {
        if (!isRecord) {
            try {
                // 设置文件名称
//                fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(System.currentTimeMillis());
                if (mAudioRecorder == null) {
                    mAudioRecorder = new AudioRecorder();
                    mAudioRecorder.setMaxDuration(getMaxSpeechTime());
                }
                filePath = AlbumUtils.randomM4aPath(AlbumUtils.getAlbumRecordFile(context, context.getPackageName(), ChatApp.getInstance().getUserId()));
                // 设置sd卡文件路径并开始录制
                mAudioRecorder.start(filePath);
                isRecord = true;
                updateMicStatus();
                voiceToast.show();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 停止录音
     */
    private void stopRecord() {
        if (isRecord) {
            isRecord = false;
            voiceToast.reset();
            voiceToast.dismiss();
            try {
                mAudioRecorder.stop();

                //-----------------------添加数据---------------------
                AlbumFile album = AlbumManageUtil.getInstance().getAlbumFile(context, filePath);
                duration = album.getDuration();
                JLog.d("录制时长"+duration);
                if (duration >= 1000 && !isCancel) {
//                    album.setMimeType(AndroidFileUtil.getMimeType(rfile));
//                    album.setPath(filePath);
//                    album.setDuration(analysisDuration(album.getPath()));
                    if (callback != null) {
                        callback.onResult(album);
                    }
//                    AlbumManageUtil.getInstance().getAlbumFile((Activity) context, fileName);
                } else {
                    File rfile = new File(filePath);
                    Utility.delete(rfile);
                    if (duration < 1000) {
                        JToast.show(context, "录音时间太短", Toast.LENGTH_SHORT);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                mAudioRecorder = new AudioRecorder();
                mAudioRecorder.setMaxDuration(getMaxSpeechTime());
            }
        }
    }

    /**
     * 将毫秒转时分秒
     *
     * @param time
     * @return
     */
    public static String generateTime(long time) {
        int totalSeconds = (int) (time / 1000);
        int seconds = totalSeconds % 60;
        int minutes = (totalSeconds / 60) % 60;
        int hours = totalSeconds / 3600;

        return hours > 0 ? String.format("%02dh%02d'%02d\"", hours, minutes, seconds) : String.format("%02d'%02d\"", minutes, seconds);
    }

    private void updateMicStatus() {
        if (isRecord) {
            if (callback != null) {
                double db = mAudioRecorder.getDecibel();
                voiceToast.setDecibelLevel(db);
                callback.onUpdate(db, duration);
            }
            handler.postDelayed(mUpdateMicStatusTimer, SPACE);
        }
    }

    private OnSpeechResultCallback callback;

    public interface OnSpeechResultCallback {
        default void onStart() {
        }

        default void onUpdate(double db, long time) {
        }

        void onResult(AlbumFile albumFile);
    }

    public static Long write(Context context, ByteString bytes) {
        String filePath = AlbumUtils.randomM4aPath(ChatApp.getInstance(), ChatApp.getInstance().getPackageName(), ChatApp.getInstance().getUserId());
        String outPath = ByteStringUtil.getNewFilePath(filePath, bytes.asReadOnlyByteBuffer());
        AlbumFile alb = AlbumManageUtil.getInstance().getAlbumFile(context, outPath);
        MediaPlayer player = new MediaPlayer();
        try {
            player.setDataSource(outPath);
            player.prepare();
            alb.setDuration(player.getDuration());
        } catch (Exception ignored) {
        } finally {
            player.release();
        }
        return AlbumManageUtil.insertAlbumFileToTable(alb, AlbumTableBean.TYPE_RECORD_FILE, "audio");
    }

    public static String analysisPath(ByteString bytes) {
        String filePath = AlbumUtils.randomM4aPath(ChatApp.getInstance(), ChatApp.getInstance().getPackageName(), ChatApp.getInstance().getUserId());
        return ByteStringUtil.getNewFilePath(filePath, bytes.asReadOnlyByteBuffer());
    }

    public static long analysisDuration(String path) {
        MediaPlayer player = new MediaPlayer();
        try {
            player.setDataSource(path);
            player.prepare();
            return player.getDuration();
        } catch (Exception ignored) {
            return 0L;
        } finally {
            player.release();
        }
    }

    /**
     * @param context
     * @param isMute  是否静音播放
     */
    public static void setAudioMute(Context context, boolean isMute) {
        AudioManager manage = ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE));

        if (isMute) {//静音
            manage.setStreamMute(AudioManager.STREAM_MUSIC, isMute);
//            manage.adjustSuggestedStreamVolume(AudioManager.ADJUST_MUTE, AudioManager.STREAM_MUSIC, 0);
        } else {//非静音
            manage.setStreamMute(AudioManager.STREAM_MUSIC, isMute);
            manage.setMicrophoneMute(false);
//            manage.adjustSuggestedStreamVolume(AudioManager.ADJUST_UNMUTE, AudioManager.STREAM_MUSIC, 0);
        }

    }
}
